package xuecheng.spring.boot.start.common.concurrent;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 线程池工具类
 *
 * @author PengXueCheng
 * @mail yingcheng1016@gmail.com
 * @date 2019/1/5 18:32
 */
@Slf4j
public class ThreadPoolUtils {

//	/**
//	 * 执行器
//	 */
//	private static final ThreadPoolTaskExecutor EXECUTOR;
//
//	/**
//	 * 核心线程数: 任务类型-CPU密集
//	 */
//	private static final int CORE_POOL_SIZE_CPU_INTENSIVE;
//	/**
//	 * 核心线程数: 任务类型-IO密集
//	 */
//	private static final int CORE_POOL_SIZE_IO_INTENSIVE;
//
//
//	/**
//	 * 处理流程
//	 * 当一个任务被提交到线程池时，首先查看线程池的核心线程是否都在执行任务，否就选择一条线程执行任务，是就执行第二步。
//	 * 查看核心线程池是否已满，不满就创建一条线程执行任务，否则执行第三步。
//	 * 查看任务队列是否已满，不满就将任务存储在任务队列中，否则执行第四步。
//	 * 查看线程池是否已满，不满就创建一条线程执行任务，否则就按照策略处理无法执行的任务。
//	 * 在ThreadPoolExecutor中表现为:
//	 * 如果当前运行的线程数小于corePoolSize，那么就创建线程来执行任务（执行时需要获取全局锁）。
//	 * 如果运行的线程大于或等于corePoolSize，那么就把task加入BlockQueue。
//	 * 如果创建的线程数量大于BlockQueue的最大容量，那么创建新线程来执行该任务。
//	 * 如果创建线程导致当前运行的线程数超过maximumPoolSize，就根据饱和策略来拒绝该任务。
//	 */
//	static {
//		// 获取当前机器cpu核数
//		int availableProcessors = Runtime.getRuntime().availableProcessors();
//		CORE_POOL_SIZE_CPU_INTENSIVE = availableProcessors + 1;
//		CORE_POOL_SIZE_IO_INTENSIVE = 2 * availableProcessors;
//
//		EXECUTOR = new ThreadPoolTaskExecutor();
//		EXECUTOR.setCorePoolSize(4);
//		EXECUTOR.setMaxPoolSize(1000);
//		EXECUTOR.setQueueCapacity(0);
//		// 设置线程拒绝策略(将任务给调用线程)
//		EXECUTOR.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//		EXECUTOR.initialize();
//	}
//
//	/**
//	 * 获取线程池
//	 *
//	 * @return
//	 */
//	public static ThreadPoolTaskExecutor getExecutor() {
//		return EXECUTOR;
//	}


    /**
     * 得到异步任务结果
     *
     * @param future
     * @return
     */
    public static <T> T getFutureResult(Future<T> future) {
        T t = null;
        try {
            t = future.get();
        } catch (InterruptedException | ExecutionException e) {
            log.error(e.getMessage(), e);
        }
        return t;
    }

    /**
     * 得到异步任务结果
     *
     * @param future
     * @param timeout 最大超时时间(单位毫秒), 超出则取消任务
     * @return
     */
    public static <T> T getFutureResult(Future<T> future, long timeout) {
        T t = null;
        try {
            t = future.get(timeout, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            log.error(e.getMessage(), e);
        }
        return t;
    }


}
